查看原文
其他

【第2182期】揭秘3D互动技术在蚂蚁数字金融的应用实战

尘沫 前端早读课 2021-01-20

前言

通过游戏来提留存也当下很不错的方式。今日前端早读课文章由蚂蚁金服@尘沫分享,由@书呆授权分享。

@尘沫,RichLab 花呗借呗前端团队,目前主要研究互动技术方向。曾就职于国内三大 H5 游戏引擎商之一的 LayaBox 近五年时间,是 LayaAir3D 的核心作者,曾贡献了 LayaAir3D 95% 的代码,半年前我来到蚂蚁开始主导 Oasis 引擎架构相关的工作。

正文从这开始~~

我分享的内容主要包含三部分:

  • 第一部分是数字金融业务背景下的互动趋势。

  • 第二部分是今天的重点内容,3D 互动技术的实战案例。

  • 第三部分是今天的重磅消息公布,Oasis Engine 开源计划。

数字金融业务背景下的互动趋势

我们首先介绍今天的第一部分内容,数字金融业务员背景下的互动趋势。数字金融是支付宝内的一个重要板块,主要包含了借呗、花呗、余额宝、芝麻信用、蚂蚁财富等,相信大家在日常的使用都接触过。数字金融具有严肃性高、工具属性强等特点。比如一个理财产品由于其专业性导致其比较严肃和高门槛,在用于眼里也只是一个单纯的金融工具,用完即走,缺少用户粘度。在数字金融的运营场景中,我们利用互动技术娱乐性和游戏化等特点达成了降低金融门槛和提升用户粘度量大核心目标。

在数字金融中我们有非常多的互动案例,今天我们挑选了四个比较典型的互动案例给大家介绍,相信很多人曾经都体验过。

  • 第一个是花呗双十一的动画/特效案例,中间的花小呗可以根据手机的陀螺仪进行旋转,形象也非常的呆萌,不仅增强了用户吸引力,还增强品了牌形象塑造。

  • 第二个是借呗双十一的飞船游戏案例,借呗相对于花呗严肃性更高,工具属性更强。飞船游戏可以让用户边玩边拿免息券,达成了降低用户认知门槛和提升产品亲和力的目标。

  • 第三个是攒黄金的仿真案例,原本攒黄金的过程只是一串冷冰冰的数字,我们将用户最后攒黄金得到的实物呈现在用户眼前,效果非常的逼真,增强了用户攒黄金过程中的代入感。

  • 最后一个是花呗提额的创意互动案例,当时在抖音专题的播放量达到了几亿次,效果非常的惊艳,该互动增强了社交传播,给用户带来了惊喜和新奇的体验。

3D互动技术的实战案例

接下来我们开始讲解今天的重点内容,3D互动技术的实战案例。本次分享我们选择了余额宝七周年跑酷项目作为今天的实战案例,余额宝在七周年之际通过跑酷游戏给用户传播攒钱心智。右边是我们的游戏体验二维吗,大家可以直接使用支付宝扫一扫进行体验。接下来我会对整个游戏的主要研发流程进行详细的讲解。

游戏设计

首先是游戏设计阶段。这里有两张草图,虽然非常的草,但是一个游戏的创意和玩法就是从这样的草图开始诞生的。通过左边的图我们可以看出整个场景采用球面或者弧面设计,通过右边的草图我们可以看出,我们的跑酷游戏是竖版跑酷,经常玩游戏的同学知道,跑酷游戏通常分为横版和竖版。

我们提炼出了四点核心玩法。

  • 我们的游戏是给用户传播攒钱心智,所以我们以“收集金币”为目标互动。

  • 为了让整个游戏更有趣,我们提供了游戏道具获得效果加成,整体玩法也更佳丰富。

  • 为了增加用户活跃度,我们设计了获得稀缺装扮满足个人成就感的玩法。

  • 为了在好友间形成互动,我们设计了邀请好友形成分享传播的玩法。

根据玩法设计和视觉设计,我们对整个游戏进行了系统拆解。分别是跑道/建筑系统、UI 系统、角色系统和金币系统。我们对拆解出来的系统进行了进一步分析规划出代码逻辑和资源素材。

游戏研发

互动技术背后的图形引擎

接下来我们进入游戏研发阶段。首先我先介绍一下互动技术背后的图形引擎,也是就本次开发余额宝跑酷项目的三维引擎 Oasis Engine。去年烧鹅在上一届 SEE Conf 就分享过 Oasis 的相关内容并且承诺过开源。分享的结尾我会公布 Oasis Engine Runtime 的开源时间。

先来回顾一下我们为什么要做 Oasis Engine。答案就在这里,基于互动业务的诉求,我们将诉求分为三类,分别是基本、美术、开发。其中蓝色的部分比较好理解,黄色部分我会重点进行说明。

  • 基本:包括高性能、高效率、稳定性,很容易理解,这里不再赘述。

  • 美术:包括 3D 化,设计生态兼容,对于设计生态兼容 Oasis 采用开放共赢的原则,我们对 Mars、Spine、3DMax、Maya 等设计生态进行兼容,让设计师使用他们最熟悉的设计工具。最后是设计资产复用和效果炫酷,也非常好理解。

  • 开发:首先是工作流分离,工作流分离其实也非常简单,举个例子就是美术专注于设计,开发专注于逻辑,无论 “LowCode” 还是 “NoCode” 都是建立在合理的分工下。接下来是可编程渲染和 VR/AR,这个也非常好理解。然后是渲染一体化,曾经我见过前端为了开发互动业务,加载一个 3D 引擎渲染 3D 内容,又加载了一个 2D 引擎渲染 Spine 动画叠加在上面,接着为了在最上层渲染 UI 又叠加了 HTML 元素,前后叠了三层。这种做法无论在性能还是稳定性都带来极大的风险。接下来是物理功能,最后是多端发布。多端发布这里也稍微解释一下,现在我们的平台包括 H5、小程序、小游戏,Native 端包括安卓、iOS等。但是对于开发者来说他们要的很简单,一次开发到处运行。

接下来我们看一下 Oasis Engine的技术大图,Oasis Engine 包含了 Oasis Workflow 和 Oasis Runtime,Oasis Workflow 又包含 Oasis Editor 和 Oasis Store,由于 Oasis Runtime 即将对外开源,所以这里我介绍一下 Oasis Runtime 用户层的接口。

  • 实体/组件系统:Oasis 是组件系统架构,所以我们的模型、动画、物理、声音、脚本均是以组件的形式存在的。

  • 场景:主要包含场景管理等功能。

  • 渲染:包含了环境渲染,比如雾化、天空等等。然后是材质/Shader 系统,主要包含了我们常见的 PBR 材质、Blinn-phone 材质以及自定义 Shader 等功能。最后是后期处理,比如 HDR、景深、SSAO 等等。

  • 资源系统:资源系统主要包含了资源管理、加载和 GC 等功能。

  • 指令渲染:指令渲染不同于以组件,是以指令的形式驱动渲染的。

  • 工具:主要包含数学库和能力检测。

  • XR :也就是 VR/AR 功能。

场景搭建

介绍完了引擎,接下来我们进入场景搭建阶段。首先我们把美术的原始资产导入到编辑器中,稍后我们需要使用这些资产在 Oasis  Editor 中进行场景编辑。Oasis Editor 是云端编辑器,采用云端中心化管理,资产导入后可自动上云。相较于友商,我们编辑器在设计思路上全面拥抱了云端,对于开发者来说无需安装,我想把我的项目发给其他同学协作也只需发送一个 URL 即可,无需繁琐的拷贝。编辑器的云端化设计思路会打破固有思维,在用户体验上带来非常多的可能性。

接下来我们展示一下如何通过已经导入的模型快速的搭建一个场景。

除了使用编辑器编辑场景之外,我们还可以使用代码编辑场景。这里展示了代码编辑场景最主要的三个部分,分别是添加实体、添加相机和添加模型。大家可以注意到无论是编辑器还是代码编辑场景,其实都是在不停的编辑实体和组件。之前我已经提到 Oasis 采用组件系统架构,组件系统架构在灵活性和重用性具有非常大的优势。Oasis 是一个互动平台,涵盖了各领域的功能,比如3D、2D、声音、物理等。我们通常会同时组合使用这些功能,甚至我们的脚本逻辑。在面对功能复杂度和保持易用性的权衡下,我们选择了万物皆组件的组件系统架构。

接下来我们整体回顾一下场景中的实体节点信息分布以及场景的运行效果。大家可能会注意到最上方的相机,这里我说一下传统 2D 和 3D 开发的区别,传统 2D 的开发更像是是在画布上进行绘画,而 3D 开发则相当于使用摄像机进行电影拍摄,所以对于 3D 开发来说相机一个必不可少的概念,右边就是我们搭建场景后在真机运行的效果。

脚本开发

接下来我们进行脚本开发阶段。先展示如何添加脚本,前端可能都知道 React 的生命周期,Oasis 也有自己的脚本生命周期,首先我们先来看一下 Oasis 的脚本生命周期时序图,脚本也是一种特殊的组件,由于时间关系,我只列举两个比较常用的生命周期函数,第一个就是 OnAwake() ,第二个是 OnUpdate() , OnAwake 是在第一次触发为激活状态时调用,并且只调用一次。OnUpdate 是主循环更新回调,是逐帧调用。脚本系统无论是在易用性和可读性相较于事件都有明显优势。右边展示了编辑器添加脚本的过程,我们只需要将创建的脚本拖拽到实体即可。右下方展示了如何通过代码添加脚本。现在我们可以看到右边的运行效果,场景已经有了金币。

接下来我们想把金币摆放到场景中。我们对金币的摆放信息进行了预生成,存储在配置文件中,运行时直接获取布置金币场景即可。每行对应赛道前后的金币信息,每列对应赛道左中右的金币信息,1 代表出现金币,0 代表不出现金币。

我们再来看一下左边的代码,该代码是摆放一行金币的逻辑,非常简单,我们只需要取出金币的配置信息调用 setRotation()  和 setPosition()  接口即可将金币信息摆放到场景中。

接下来我们想让场景滚动起来。我们对角色采用原地不动的策略,那么我们如何模拟出人物向前奔跑的视觉呢?答案是基于相对运动原理,场景和赛道“逆向运动”的方式模拟人物向前奔跑的视觉效果。对于跑酷游戏来说除了向前奔跑的感觉,还需要无限的赛道场景。对于建筑来说,我们分为两段设计,对建筑进行逆时针旋转,当一段建筑旋转到 2 倍 theta 角时,我们将其重置为 0 度角,通过不停的循环来模拟无限建筑的视觉。对于跑道来说,我们采用不同的策略,我们使用了一个静止的模型,通过逆向循环移动贴图的方式模拟无限跑道的视觉。

接下来我们让整个建筑和金币滚动起来,我们刚才在生成金币时偷偷的将金币塞到了建筑的父节点下,因此我们只需调用左边代码的最后一行 entity.transform.setRotation()  即可让建筑和金币旋转起来。除此之外还有一个重要的点是中间的代码 if(rotationX>this.maxAngle) 这里的 maxAngle 就是我之前提到的2倍 theta 角,当角度大于 maxAngle 时,我们选准角度重置为0,并且金币也会进行相关的重置工作。现在我们可以看到右边的运行效果,建筑和金币已经滚动起来了。

刚才我们已经提到跑道采用逆向移动贴图的原理,左边就是我们的实现代码,非常简单,只需调用材质的 tillingOffset 功能即可设置实现该功能,该功能的原理是在 GPU 的顶点着色内通过增加模型的 UV 来达到让贴图滚动的效果。Oasis 引擎内置的材质包含很多开发者常用的功能。我再进行更形象的比喻,这个思路就像跑步机,跑道的模型相当于跑步机底座,跑道的贴图就像跑道的履带。现在我们可以看到右边的运行效果,跑道已经滚动起来了。

现在我们的角色还是悬空静止的状态。接下里我们要让人物奔跑起来,非常简单,我们只需在初始化阶段获取角色的动画组件并播放奔跑动作即可。我们的角色动作采用了蒙皮动画技术,但是我们的开发同学无需担心,因为我们的动画素材都是美术同学提供的,开发只需要关心播放逻辑。现在我们看右边的运行效果,角色已经奔跑起来了。

接下来我们想让金币旋转起来,我们只需要创建一个金币脚本添加到金币上,并且重载金币的 onUpdate 函数调用实体的 transform.rotateXYZ() 函数就可以让金币绕着 Y 轴进行自旋转。其中的 deltaTime 是每帧之间的间隔时间。

接下来我们我们想让人物和金币产生碰撞,首先我们需要给金币和角色添加碰撞组件。我们给金币和角色均添加球形碰撞器,代表金币和角色可以被碰撞,我们再给角色添加了碰撞检测器,代表了角色可以主动发起碰撞。然后我们要开始进行金币碰撞逻辑的处理,让角色和金币碰撞后金币消失。我们只需继续重载刚才金币脚本的 onTriggerEnter() 函数并且调用 this.entity.isActive=false 即可让金币消失。

效果增强

接来我们想让跑酷游戏更酷一些。我们想让角色和金币碰撞时产生一个粒子效果,我们怎么做呢?我们可以给角色添加一个粒子组件,左边展示了粒子组件的属性面板,同样中间我们也提供了代码编辑粒子的方式,但是我不建议大家使用代码编辑粒子的方式,因为制作粒子效果是一个反复调参试探的过程,通过可视化的编辑器是一个非常高效的方式,使用代码制作粒子效率非常低,另外这个工作本身也不应该属于开发。

我们还想让效果再酷一些,我们还想在金币和人物碰撞时产生边缘光照效果。边缘光照效果可以利用片元着色器编写,其原理主要是利用视线的方向和模型的法线进行 dot 点积,当两者为 90 度时叠加最大亮度的边缘光照颜色,0 度时最弱。Oasis 是一个侧重 GPU 能力的引擎,着色器不仅仅是处理渲染逻辑,我们可以把顶点逻辑、轨迹逻辑、蒙皮逻辑等都放到 GPU 中执行,充分利用 GPU 的并行能力。

接下来我们进行一个效果回顾,从场景摆放到让建筑/赛道滚动起来,再到添加人物/金币的旋转动画,再到添加碰撞逻辑,一个跑酷游戏的主体逻辑就完成了,最后经过一系列的产品化我们完成了最终产品。

性能优化

前面已经完成了游戏的主体开发。我们的项目是运行在支付宝平台,意味最终会在亿级数量的设备中运行,涵盖多种机型。我们如何让其在低端机流畅的运行也是整个研发流程里非常重要的一部分,接下来我们简单介绍一下如何让其达到金融级稳定性。

首先我们对模型进行减面优化,我们最初拿到的模型是图片左边的三角面数量,由于跑酷游戏是固定视角,看不到模型的背面,于是我们利用跑酷游戏的特点将场景的背面进行了抠除,经过优化后三角面的数量减少了50%,减轻了 GPU 渲染三角面的压力。

接下来我们继续对模型进行优化,前端可能都知道 Css Sprite,原理是类似的,我们通过把单个模型的贴图、材质、以及网格进行了合并,这样 GPU 就可以通过一个渲染批次完成多个模型的渲染,减轻了 GPU 渲染批次的压力。

刚才讲完了模型的优化,接下来我们对贴图进行优化,三维开发中往往存在大量材质,大量材质包含了大量的贴图,大量的贴图就带来了大量的显存,大量的显存就带来了 Crash 风险。我们采用了 GPU 纹理压缩方案来降低显存,但我们又面临一个GPU 纹理压缩格式碎片化的问题。比如iOS 支持 PVR 和 ASTC, Android 支持 ETC 和 ASTC,于是我们提供了全平台纹理压缩解决方案,在运行时动态检测运行平台,自动选择对应的纹理压缩格式。最后的结果是我们把一张1024x1024的纹理显存从5.33M 降低到了600K,节省了约80%的显存。

刚才都是机缘的优化,我们再讲一个程序相关的优化,我们在金币对象的管理上使用了对象池。对象池其实非常简单,但却非常重要,在互动业务的开发中几乎是必备的。对象池可以减少主循环过程中创建对象带来的开销和避免频繁创建释放对象带来的 GC。GC 可以说是一个隐形的性能杀手。最后我们 iOS 的闪退率是万分之 0.1,Android 的闪退率是万分之0.4,总闪退率是万 0.3。

目前 Oasis 在经济体共支持 30 余个项目,10 余个 BU。今天我分享的内容只涉及了 Oasis Engine 一小部分功能,Oasis 目前也处在一个高速发展期,希望大家可以持续的关注我们。

Oasis Engine 开源计划

接下来就是我们最后的重磅消息公布,Oasis Engine 开源计划。Oasis Engine 的 Runtime 会在 2 月 1 日正式开源。

为你推荐


【第2180期】Ant Design 设计工程化


【第1913期】Math.sign:在Javascript中如何检查一个数字是正数还是负数


欢迎自荐投稿,前端早读课等你来

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存